package com.jeegot.mall.service.impl;

import cn.hutool.core.date.LocalDateTimeUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jeegot.common.exception.JeegotException;
import com.jeegot.core.payment.platform.WxPaymentPlatform;
import com.jeegot.core.processor.OrderPayAmountProcessorManager;
import com.jeegot.core.utils.SnowFlake;
import com.jeegot.core.utils.StrUtils;
import com.jeegot.entity.PaymentRecord;
import com.jeegot.mall.aspect.OrderPayAmount;
import com.jeegot.mall.entity.*;
import com.jeegot.mall.mapper.OrderMapper;
import com.jeegot.mall.service.*;
import com.jeegot.service.IPaymentRecordService;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 订单表 服务实现类
 * </p>
 *
 * @author wjun_java@163.com
 * @since 2021-06-14
 */
@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Order> implements IOrderService {

	@Autowired
	private IOrderItemService orderItemService;

	@Autowired
	private IProductService productService;

	@Autowired
	private IDeliveryAddressService deliveryAddressService;

	@Autowired
	private IProductSkuItemService productSkuItemService;

	@Autowired
	private IPostageTemplateService postageTemplateService;

	@Autowired
	private IPaymentRecordService paymentRecordService;

	@Autowired
	private IOrderDeliveryService orderDeliveryService;

	@Autowired
	private OrderPayAmountProcessorManager orderPayAmountProcessorManager;

	private static final SnowFlake SNOW_FLAKE = new SnowFlake(1, 1);

	public static String getOrderSN() {
		return String.valueOf(SNOW_FLAKE.genNextId());
	}

	@Override
	public Page<OrderVo> pageOrder(Page pageParam, QueryWrapper queryWrapper) {
		return getBaseMapper().pageOrder(pageParam, queryWrapper);
	}

	@Override
	@Transactional
	@OrderPayAmount
	public Long createOrder(CreateOrderParam createOrderParam) throws Exception {

		if(createOrderParam.getUserId() == null) throw new JeegotException("user id is null");

		DeliveryAddress address = deliveryAddressService.getById(createOrderParam.getAddressId());
		if(address == null) throw new JeegotException("收货地址不存在");

		//订单项
		List<OrderItem> orderItemList = new ArrayList<>();

		List<ProductParam> products = createOrderParam.getProducts();
		if(products == null || products.size()<=0) {
			throw new JeegotException("未找到需购买商品项");
		}

		Product firstProduct = null; //第一个商品名称作为订单标题
		for (ProductParam item : products) {
			if(firstProduct == null) {
				firstProduct = productService.getById(item.getId());
			}
			Long num = item.getNum();
			BigDecimal productPrice = getProductPrice(item); //获取商品单价
			BigDecimal postageAmount = postageTemplateService.getPostageAmount(item, address.getAddress());
			OrderItem orderItem = new OrderItem();
			orderItem.setProductId(item.getId());
			orderItem.setProductCount(num.intValue());
			orderItem.setPostageCost(postageAmount);
			orderItem.setTotalAmount(new BigDecimal(num).multiply(productPrice));
			orderItem.setSku(item.getSku());
			orderItemList.add(orderItem);
		}

		Order order = new Order();
		order.setUserId(createOrderParam.getUserId());
		order.setOrderSn(getOrderSN());
		order.setOrderAmount(orderItemList.stream().map(OrderItem::getTotalAmount).reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, BigDecimal.ROUND_HALF_UP));
		order.setPayStatus(Order.STATUS_PAY_PRE);
		order.setBuyerMsg(createOrderParam.getBuyerMsg());
		order.setOrderTitle(firstProduct.getTitle());

		order.setConsigneeUsername(address.getName());
		order.setConsigneeMobile(address.getMobile());
		order.setConsigneeAddrDetail(address.getAddress() + address.getStreet());

		order.setInvoiceStatus(Order.INVOICE_STATUS_NOT_APPLY);

		//计算邮费
		order.setPostageAmount(orderItemList.stream().map(OrderItem::getPostageCost).reduce(BigDecimal.ZERO, BigDecimal::add).setScale(2, BigDecimal.ROUND_HALF_UP));

		order.setPayAmount(order.getOrderAmount().add(order.getPostageAmount()).setScale(2, BigDecimal.ROUND_HALF_UP));

		order.setTradeStatus(Order.TRADE_STATUS_TRADING);
		order.setStatus(Order.ORDER_STATUS_NORMAL);
		save(order);

		for (OrderItem orderItem : orderItemList) {
			orderItem.setOrderId(order.getId());
			orderItem.setOrderSn(order.getOrderSn());
			Product product = productService.getById(orderItem.getProductId());
			orderItem.setSellerId(product.getUserId());
		}

		orderItemService.saveBatch(orderItemList);

		return order.getId();
	}

	@Override
	@Transactional
	public PaymentRecord preparePaymentRecord(Order order, String openid, String ip) {
		PaymentRecord paymentRecord = paymentRecordService.getById(order.getPaymentId());
		if(paymentRecord == null) {
			paymentRecord = new PaymentRecord();
			paymentRecord.setTrxNo(StrUtils.uuid());
			paymentRecord.setTrxType(PaymentRecord.TRX_TYPE_ORDER);
			paymentRecord.setTrxNonceStr(StrUtils.uuid());
			paymentRecord.setPayType(WxPaymentPlatform.platformName);
			paymentRecord.setOrderIp(ip);
			paymentRecord.setPayStatus(Order.STATUS_PAY_PRE);
			paymentRecord.setProductRelativeId(order.getId());
			paymentRecord.setPayAmount(order.getPayAmount());
			paymentRecord.setPayerFee(BigDecimal.ZERO);
			paymentRecord.setPaySuccessAmount(order.getPayAmount());
			paymentRecord.setUserId(order.getUserId());
			paymentRecord.setPaySuccessTime(LocalDateTime.now());
			paymentRecord.setThirdpartyUserOpenid(openid);
			paymentRecordService.save(paymentRecord);
			order.setPaymentId(paymentRecord.getId());
			updateById(order);
		}
		return paymentRecord;
	}

	@Override
	public OrderCountVo getUCenterOrderCount(Long userId) {
		return getBaseMapper().getUCenterOrderCount(userId);
	}

	@Override
	public Page<Order> pageOrderOfApi(Page pageParam, QueryWrapper queryWrapper) {
		Page<Order> orderPage = getBaseMapper().pageOrderOfApi(pageParam, queryWrapper);
		return orderPage;
	}

	@Override
	public OrderVo getOrderDetail(Long orderId) {
		OrderVo orderDetail = getBaseMapper().getOrderDetail(orderId);
		return orderDetail;
	}

	@Override
	public OrderDelivery getOrderDelivery(Long orderId) {
		QueryWrapper queryWrapper = new QueryWrapper();
		queryWrapper.eq("order_id", orderId);
		return orderDeliveryService.getOne(queryWrapper);
	}

	@Override
	@Transactional
	public void doOrderDelivery(Long orderId, String expName, String billNumber, String deliveryTime) throws Exception {
		Order order = getById(orderId);
		if(order == null) {
			throw new JeegotException("订单不存在");
		}

		if(order.getDeliveryStatus() == Order.DELIVERY_STATUS_FINISHED) {
			throw new JeegotException("买家已确认收货");
		}

		if(order.getDeliveryStatus() == Order.DELIVERY_STATUS_NONEED) {
			throw new JeegotException("无需发货");
		}

		OrderDelivery orderDelivery = getOrderDelivery(orderId);
		if(orderDelivery == null) {
			orderDelivery = new OrderDelivery();
			orderDelivery.setOrderId(orderId);
		}

		orderDelivery.setExpName(expName);
		orderDelivery.setBillNumber(billNumber);
		orderDelivery.setDeliveryTime(LocalDateTimeUtil.parse(deliveryTime, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
		orderDeliveryService.saveOrUpdate(orderDelivery);

		order.setDeliveryId(orderDelivery.getId());
		order.setDeliveryStatus(Order.DELIVERY_STATUS_DELIVERIED);
		updateById(order);
	}

	BigDecimal getProductPrice(ProductParam productParam) {
		if(StringUtils.isNotBlank(productParam.getSku())) {
			ProductSkuItem productSkuItem = productSkuItemService.getProductSkuItem(productParam.getId(), productParam.getSku());
			if(productSkuItem != null) {
				return productSkuItem.getPrice();
			}
		}
		Product product = productService.getById(productParam.getId());
		return product == null ? BigDecimal.ZERO : product.getPrice();
	}

}
